import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
  HttpStatus,
  Inject,
  Logger,
} from '@nestjs/common';
import { Request, Response } from 'express';
import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';
import * as _ from 'lodash';
interface exceptionResponse {
  statusCode?: number;
  message?: string;
}

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter<HttpException> {
  constructor(
    @Inject(WINSTON_MODULE_NEST_PROVIDER)
    private readonly logger: Logger,
  ) {}
  catch(exception: HttpException, host: ArgumentsHost): any {
    // exception 当前正在处理的异常对象
    // host 是转递原始处理程序的参数
    // console.log('进入全局异常过滤器 filter');
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    // HttpException 基础异常类
    // 如果是自定义异常类抛出自定义status
    // 如果是内置HTTP异常类，抛出内置status内容
    const status =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;
    const exceptionResponse: exceptionResponse =
      exception.getResponse() as exceptionResponse;
    const message = exceptionResponse?.message;
    // 这里的message可以是字符串，也可能是数组 (主要是为了把错误信息一项项的返回) , 可以不这么做
    let msg = '';
    if (_.isString(message)) {
      msg = exceptionResponse?.message;
    } else if (_.isArray(message)) {
      msg =
        exceptionResponse?.message.length > 0
          ? exceptionResponse?.message[0]
          : '';
    }
    // 抛出错误信息
    const msgLog = {
      code: exceptionResponse?.statusCode
        ? exceptionResponse?.statusCode
        : status, // 系统错误状态
      timestamp: new Date().toISOString(), // 错误日期
      path: request.url, // 错误路由
      msg: msg,
      data: null, // 错误消息内容体
    };
    // 打印并记录错误综合日志
    this.logger.error(
      '错误信息',
      JSON.stringify(msgLog),
      'HttpExceptionFilter',
    );
    response.status(status).json(msgLog);
  }
}
